#    Copyright 2010 Tri-County Electric Cooperative, St. Matthews, South Carolina
#    This file is part of COOPGIS.
#    COOPGIS is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#    COOPGIS is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#    You should have received a copy of the GNU General Public License
#    along with COOPGIS.  If not, see <http://www.gnu.org/licenses/>.

#************************BEGIN Add Include Files to Path************************
import sys
NeededPaths=['/opt/coopgis/djangoproject/include', '/opt/coopgis/djangoproject']
for path in NeededPaths:
    if(not path in sys.path):
        sys.path.append(path)
#************************END   Add Include Files to Path************************
import COOPGIS_Ajax, COOPGIS_GPS, COOPGIS_Misc, COOPGIS_FormMisc, COOPGIS_ReportLab, COOPGIS_String, COOPGIS_Update, COOPGIS_FormStaker
import COOPGIS_FormGeography, COOPGIS_DynamicTemplate, COOPGIS_FormCIS
from djangoproject.models import *
import os, csv, shutil, datetime, time, reportlab, djangoproject.settings, random
from django.contrib.gis.db import models
from django.contrib.gis.geos import *
from django.http import HttpResponse
from django.contrib import admin
from django.template import Context, loader
import djangoproject.settings
import _mysql as mysql
from models import *
from django import forms
try:
    import CIS, AMR
except:
    pass
import COOPGIS_FormMaintenance

from django.db import transaction

@transaction.commit_on_success
def MainMenu(request):
    import django.db
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/gisreportmainmenu.html')
        c = Context({'LoginStatus' : LoginStatus})
        return HttpResponse(t.render(c))
    t = loader.get_template('/opt/coopgis/djangoproject/templates/gisreportmainmenu.html')
    c = Context({'LoginStatus' : LoginStatus})
    return HttpResponse(t.render(c))


@transaction.commit_on_success
def PrimarySecondaryServiceIndicatorCheck(request):
    import django.db
    GenericReportTitle='COOPGIS Assemblies Missing Proper Primary, Secondary, or Service Indicators'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    Temp.append('Span'.ljust(20) + 'CompatibleUnit'.ljust(20) + 'PrimaryIndicator'.ljust(20) + 'SecondaryIndicator'.ljust(20) + 'ServiceIndicator'.ljust(20))
    installStatus=InstallStatus.objects.filter(Name='Existing')
    SpanAssemblies=Assembly.objects.exclude(PrimaryIndicator=True).exclude(SecondaryIndicator=True).exclude(ServiceIndicator=True).exclude(Span__isnull=True).filter(InstallStatus=installStatus) \
               | Assembly.objects.filter(PrimaryIndicator=True).filter(SecondaryIndicator=True).filter(ServiceIndicator=True).exclude(Span__isnull=True).filter(InstallStatus=installStatus) \
               | Assembly.objects.filter(PrimaryIndicator=True).filter(SecondaryIndicator=True).exclude(Span__isnull=True).filter(InstallStatus=installStatus) \
               | Assembly.objects.filter(SecondaryIndicator=True).filter(ServiceIndicator=True).exclude(Span__isnull=True).filter(InstallStatus=installStatus) \
               | Assembly.objects.filter(PrimaryIndicator=True).filter(ServiceIndicator=True).exclude(Span__isnull=True).filter(InstallStatus=installStatus)
    Temp.append('Span Assemblies:   ' + str(SpanAssemblies.count()))
    if(SpanAssemblies.count() > 5000):
        SpanAssemblies=SpanAssemblies[:5000]
    DisplayedAssemblyList=[]
    for assembly in SpanAssemblies:
        if(not assembly in DisplayedAssemblyList):
            DisplayedAssemblyList.append(assembly)
            Spanid=str(assembly.Span.id)
            Temp.append(Spanid.ljust(20) + str(assembly.CompatibleUnit).ljust(20) + str(assembly.PrimaryIndicator).ljust(20) + str(assembly.SecondaryIndicator).ljust(20) + str(assembly.ServiceIndicator).ljust(20)) 
    Temp.append('')
    Temp.append('')
    Temp.append('Station'.ljust(20) + 'CompatibleUnit'.ljust(20) + 'PrimaryIndicator'.ljust(20) + 'SecondaryIndicator'.ljust(20) + 'ServiceIndicator'.ljust(20))
    StationAssemblies=Assembly.objects.exclude(PrimaryIndicator=True).exclude(SecondaryIndicator=True).exclude(ServiceIndicator=True).exclude(Station__isnull=True).filter(InstallStatus=installStatus) \
               | Assembly.objects.filter(PrimaryIndicator=True).filter(SecondaryIndicator=True).filter(ServiceIndicator=True).exclude(Station__isnull=True).filter(InstallStatus=installStatus) \
               | Assembly.objects.filter(PrimaryIndicator=True).filter(SecondaryIndicator=True).exclude(Station__isnull=True).filter(InstallStatus=installStatus) \
               | Assembly.objects.filter(SecondaryIndicator=True).filter(ServiceIndicator=True).exclude(Station__isnull=True).filter(InstallStatus=installStatus) \
               | Assembly.objects.filter(PrimaryIndicator=True).filter(ServiceIndicator=True).exclude(Station__isnull=True).filter(InstallStatus=installStatus)
    Temp.append('StationAssemblies:   ' + str(StationAssemblies.count()))
    if(StationAssemblies.count() > 5000):
        StationAssemblies=StationAssemblies[:5000]
    DisplayedAssemblyList=[]
    for assembly in StationAssemblies:
        if(not assembly in DisplayedAssemblyList):
            DisplayedAssemblyList.append(assembly)
            Stationid=str(assembly.Station.id)
            Temp.append(Stationid.ljust(20) + str(assembly.CompatibleUnit).ljust(20) + str(assembly.PrimaryIndicator).ljust(20) + str(assembly.SecondaryIndicator).ljust(20) + str(assembly.ServiceIndicator).ljust(20)) 

    Preformatted='\n'.join(Temp)
   #End Data Gathering Tasks
    GenericMessage=''
    
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))






@transaction.commit_on_success
def StakerReportSummary(request):
    import django.db
    GenericReportTitle='COOPGIS Staker Reports Summary 2012'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    StartDate=datetime.date(year=2012, month=01, day=01)
    EndDate=datetime.date(year=2013, month=01, day=01)
    Temp.append('Start Date:  '.ljust(50) + str(StartDate))
    Temp.append('End Date:  '.ljust(50)  + str(EndDate))

    WorkOrderNumbers=StakerWorkOrder.objects.all().values('WorkOrderNumber')
    TwoDigitWorkOrderNumberList=[]
    for i in WorkOrderNumbers:
        i = i['WorkOrderNumber']
        if(not len(i) > 2):
            if(not i in TwoDigitWorkOrderNumberList):
                #TwoDigitWorkOrderNumberList.append(i)
                pass
        elif(not i[:2] in TwoDigitWorkOrderNumberList):
            TwoDigitWorkOrderNumberList.append(i[:2])

    TwoDigitWorkOrderNumberList.sort()
    TwoDigitWorkOrderNumberList.append('')
    for i in TwoDigitWorkOrderNumberList:
        if i == '':
            Temp.append('Totals:  ') 

        NumberOfStakerWorkOrdersStarted=StakerWorkOrder.objects.exclude(OutToConstructionStartIndicator=True).filter(StakerPhaseStartDate__lt=EndDate).filter(WorkOrderNumber__startswith=i).exclude(DeletedIndicator=True).count()
        Temp.append(str(i).ljust(5) + 'Staker Work Orders Started'.ljust(50) + str(NumberOfStakerWorkOrdersStarted))

        NumberOfStakerWorkOrdersOutToConstruction=StakerWorkOrder.objects.exclude(VerificationPhaseStartIndicator=True).filter(OutToConstructionStartDate__gte=StartDate).filter(OutToConstructionStartDate__lt=EndDate).filter(WorkOrderNumber__startswith=i).exclude(DeletedIndicator=True).count()
        Temp.append(str(i).ljust(5) + 'Staker Work Orders Out To Construction'.ljust(50) + str(NumberOfStakerWorkOrdersOutToConstruction))

        NumberOfStakerWorkOrdersInVerification=StakerWorkOrder.objects.exclude(ArchivedIndicator=True).filter(VerificationPhaseStartDate__gte=StartDate).filter(VerificationPhaseStartDate__lt=EndDate).filter(WorkOrderNumber__startswith=i).exclude(DeletedIndicator=True).count()
        Temp.append(str(i).ljust(5) + 'Staker Work Orders In Verification'.ljust(50) + str(NumberOfStakerWorkOrdersInVerification))

        NumberOfStakerWorkOrdersArchived=StakerWorkOrder.objects.filter(ArchivedDate__gte=StartDate).filter(ArchivedDate__lt=EndDate).filter(WorkOrderNumber__startswith=i).exclude(DeletedIndicator=True).count()
        Temp.append(str(i).ljust(5) + 'Staker Work Orders Archived'.ljust(50) + str(NumberOfStakerWorkOrdersArchived))

    #NumberOfStakerWorkOrders


    Preformatted='\n'.join(Temp)
   #End Data Gathering Tasks
    GenericMessage=''
    
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))





@transaction.commit_on_success
def TagNumber(request):
    import django.db
    GenericReportTitle='COOPGIS Missing/Incorrect TagNumbers'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))


    Temp=[]
    Temp.append('CircuitNumber'.ljust(20) + 'Station'.ljust(20) + 'CompatibleUnit'.ljust(20) + 'TagNumber'.ljust(20))    
    Assemblies=Assembly.objects.filter(CompatibleUnit__PoleIndicator=True).filter(InstallStatus__Name='Existing') | \
               Assembly.objects.filter(CompatibleUnit__TransformerIndicator=True).filter(CompatibleUnit__NormallyUndergroundIndicator=True).filter(InstallStatus__Name='Existing') | \
               Assembly.objects.filter(CompatibleUnit__VaultIndicator=True).filter(InstallStatus__Name='Existing').order_by('CircuitNumber')
    ListToPrint = []
    for assembly in Assemblies:
        if(not len(assembly.TagNumber) == 6) or (not assembly.TagNumber[0] in ['1', '2', '3']): #if tag length is either less than 6 or tag value is not equal to 1,2,3
            if(assembly.CompatibleUnit.VaultIndicator==True): #if it is a vault
                if(Assembly.objects.filter(Station=assembly.Station).filter(CompatibleUnit__PoleIndicator=True)): #If there is a pole in the same station as the vault, then the vault will not have a tag number
                    continue
            ListToPrint.append(assembly)
#    Areas = [('2','St Matthews'), ('3','Eastover'), ('4','Sandy Run'), ('5','Vance'), ('6','Burke Road'), ('7','Richland 1/2'),
#             ('8','Silver Lake'), ('9','Hopkins'), ('10','Three Bridges'), ('11','Hammonds Cross'), ('12','Wells'), ('13', 'Oaks') ]
    StMatthewsList = []
    EastoverList = []
    SandyRunList = []
    VanceList = []
    BurkeRoadList = []
    RichlandList = []
    SilverLakeList = []
    HopkinsList = []
    ThreeBridgesList = []
    HammondsCrossList = []
    WellsList = []
    OaksList = []
    UnknownList = []
    for assembly in ListToPrint:
        if str(assembly.CircuitNumber).startswith('2'):
            StMatthewsList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('3'):
            EastoverList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('4'):
            SandyRunList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('5'):
            VanceList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('6'):
            BurkeRoadList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('7'):
            RichlandList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('8'):
            SilverLakeList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('9'):
            HopkinsList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('10'):
            ThreeBridgesList.append(assembly)         
        elif str(assembly.CircuitNumber).startswith('11'):
            HammondsCrossList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('12'):                
            WellsList.append(assembly)
        elif str(assembly.CircuitNumber).startswith('13'):
            OaksList.append(assembly)
        else:
            UnknownList.append(assembly)
    Temp.append('ST MATTHEWS')
    for assembly in StMatthewsList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nEASTOVER')
    for assembly in EastoverList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nSANDYRUN')
    for assembly in SandyRunList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nVANCE')
    for assembly in VanceList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nBURKE ROAD')
    for assembly in BurkeRoadList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nRICHLAND 1/2')
    for assembly in RichlandList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nSILVER LAKE')
    for assembly in SilverLakeList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nHOPKINS')
    for assembly in HopkinsList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nTHREE BRIDGES')
    for assembly in ThreeBridgesList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nHAMMONDS CROSS')
    for assembly in HammondsCrossList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nWELLS')
    for assembly in WellsList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nOAKS')
    for assembly in OaksList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Temp.append('\n\nUNKNOWN LOCATION')
    for assembly in UnknownList:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20) + str(assembly.TagNumber).ljust(20))
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))

@transaction.commit_on_success
def EmptyLocations(request):
    import django.db
    GenericReportTitle='COOPGIS Empty Spans and Stations'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    Temp.append('Station'.ljust(20))    
    Stations=Station.objects.all().order_by('id')
    for station in Stations:
        if Assembly.objects.filter(Station=station).count():
            continue
        SymbologyStationWorkOrders=SymbologyStakerWorkOrderStation.objects.filter(Station=station)
        WorkOrderStatus=[]
        for i in SymbologyStationWorkOrders:
            WorkOrderInfo=i.StakerWorkOrder.GetIDPhaseString()
            if WorkOrderInfo in WorkOrderStatus:
                continue
            WorkOrderStatus.append(WorkOrderInfo)
        Temp.append(str(station.id).ljust(20) + str(WorkOrderStatus))
    Temp.append('')
    Temp.append('')
    Temp.append('')
    Temp.append('Span'.ljust(20) + 'WorkOrders')  
    Spans=Span.objects.all().order_by('id')
    for span in Spans:
        if Assembly.objects.filter(Span=span).count():
            continue
        SymbologySpanWorkOrders=SymbologyStakerWorkOrderSpan.objects.filter(Span=span)
        WorkOrderStatus=[]
        for i in SymbologySpanWorkOrders:
            WorkOrderInfo=i.StakerWorkOrder.GetIDPhaseString()
            if WorkOrderInfo in WorkOrderStatus:
                continue
            WorkOrderStatus.append(WorkOrderInfo)
        Temp.append(str(span.id).ljust(20) + str(WorkOrderStatus))
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))


def SinglePhaseSpanMakeSureOkToVisit(span, SpansAlreadyVisited, SpansToVisit, CurrentSpan, CurrentStation, CircuitNumber, VisitedThreePhaseTransformerIndicatorList):
    """Returns True if the span should be visited, returns false if anything is blocking visiting the span"""
    if(span in SpansAlreadyVisited):
        return False
    if(span in SpansToVisit):
        return False
    if(span == CurrentSpan):
        return False
    if(djangoproject.models.symbology.SymbologyOpenPoint.objects.filter(Station=CurrentStation).filter(CircuitNumber=CircuitNumber)):
        return False
    if(SymbologyOpenPoint.objects.filter(Point__distance_lte=(span.Line, .1)).filter(CircuitNumber=CircuitNumber)):
        return False
    if(Assembly.objects.filter(Station=span.FarStation(CurrentStation)).filter(CompatibleUnit__Name__startswith='A5').filter(InstallStatus__Name__in=['Existing', 'Remove']).count() > 1):
        return False #multiple A5 assemblies at a station represent a split in the line between two phases, so do not follow spans at this type of station so the regions remain separated
    if(Assembly.objects.filter(Station=span.FarStation(CurrentStation)).filter(CompatibleUnit__Name__startswith='VA5').filter(InstallStatus__Name__in=['Existing', 'Remove']).count() > 1):
        return False #multiple VA5 assemblies at a station represent a split in the line between two phases, so do not follow spans at this type of station so the regions remain separated
    if(VisitedThreePhaseTransformerIndicatorList[0] and Assembly.objects.filter(Span=span).filter(PrimaryIndicator=True).filter(CompatibleUnit__ConductorIndicator=True).count()):
        return False  #If a Transformer off of a 3 phase line has been visited, then do not visit any primary spans.
    if(Assembly.objects.filter(Station=span.FarStation(CurrentStation)).filter(CompatibleUnit__Name='PHASE BRANCH').count()):
        return False #PHASE BRANCH is used where two phases branch off of a single line and there is not another identifiable assembly representing this.  
    return True


def GetSinglePhaseSpansToVisit(CurrentStation, SpansAlreadyVisited, SpansToVisit, CurrentSpan, CircuitNumber, VisitedThreePhaseTransformerIndicatorList):
    Spans=CurrentStation.GetNearbySpans()
    PossibleSpansToVisit=[]
    ThreePhaseSpans=[]
    for span in Spans:
        if(len(span.GetPhaseCode(IncludeNeutral=False, CircuitNumber=CircuitNumber)) == 1):
            PossibleSpansToVisit.append(span)
        elif(len(span.GetPhaseCode(IncludeNeutral=False, CircuitNumber=CircuitNumber)) in [3,4]):
            ThreePhaseSpans.append(span)
    ConfirmedSpansToVisit=[]
    if(len(ThreePhaseSpans) < 2):
        for span in PossibleSpansToVisit:
            if(SinglePhaseSpanMakeSureOkToVisit(span, SpansAlreadyVisited, SpansToVisit, CurrentSpan, CurrentStation, CircuitNumber, VisitedThreePhaseTransformerIndicatorList)):
                ConfirmedSpansToVisit.append(span)
        return ConfirmedSpansToVisit #No Need to check to see if they intersect 3 phase spans if there is 0 or 1 3 phase spans
    else:  #Get a list of lines that can be drawn by far stations of 3 phase spans
        ThreePhaseSpanLines=[]
        ThreePhaseSpanStations=[]
        for span in ThreePhaseSpans:
            ThreePhaseSpanStations.append(span.FarStation(CurrentStation))
        for station in ThreePhaseSpanStations:
            for station2 in ThreePhaseSpanStations:
                if(not station == station2):
                    ThreePhaseSpanLines.append(LineString(station.Point, station2.Point, srid=station.Point.srid))
    for span in PossibleSpansToVisit:  #If the span does not intersect any of the 3 phase lines, then add it to the list of spans to visit
        if(not CurrentSpan):
            break
        ThreePhaseIntersection=False
        for line in ThreePhaseSpanLines:
            try:
                if(line.intersects(LineString(span.FarStation(CurrentStation).Point, CurrentSpan.FarStation(CurrentStation).Point))):
                    #raise(Exception('Here'))
                    ThreePhaseIntersection=True
            except AttributeError:   #FIXME There is a bug where the current station is not always associated with the current span, Span 65996 for example.
                pass
        if((not ThreePhaseIntersection) and SinglePhaseSpanMakeSureOkToVisit(span, SpansAlreadyVisited, SpansToVisit, CurrentSpan, CurrentStation, CircuitNumber, VisitedThreePhaseTransformerIndicatorList)):
            ConfirmedSpansToVisit.append(span)
    return ConfirmedSpansToVisit

def GetOneSinglePhaseSpanToVisit(CurrentStation, SpansAlreadyVisited, SpansToVisit, CurrentSpan, CircuitNumber, VisitedThreePhaseTransformerIndicatorList):
    Spans=CurrentStation.GetNearbySpans()
    PossibleSpansToVisit=[]
    ThreePhaseSpans=[]
    for span in Spans:
        if(len(span.GetPhaseCode(IncludeNeutral=False, CircuitNumber=CircuitNumber)) == 1):
            PossibleSpansToVisit.append(span)
        elif(len(span.GetPhaseCode(IncludeNeutral=False, CircuitNumber=CircuitNumber)) in [3,4]):
            ThreePhaseSpans.append(span)
    ConfirmedSpansToVisit=[]
    if(len(ThreePhaseSpans) < 2):
        for span in PossibleSpansToVisit:
            if(SinglePhaseSpanMakeSureOkToVisit(span, SpansAlreadyVisited, SpansToVisit, CurrentSpan, CurrentStation, CircuitNumber, VisitedThreePhaseTransformerIndicatorList)):
                ConfirmedSpansToVisit.append(span)
        if(ConfirmedSpansToVisit):
            return [ConfirmedSpansToVisit[0]] #No Need to check to see if they intersect 3 phase spans if there is 0 or 1 3 phase spans
        else:
            return []
    else:  #Get a list of lines that can be drawn by far stations of 3 phase spans
        ThreePhaseSpanLines=[]
        ThreePhaseSpanStations=[]
        for span in ThreePhaseSpans:
            ThreePhaseSpanStations.append(span.FarStation(CurrentStation))
        for station in ThreePhaseSpanStations:
            for station2 in ThreePhaseSpanStations:
                if(not station == station2):
                    ThreePhaseSpanLines.append(LineString(station.Point, station2.Point, srid=station.Point.srid))
    for span in PossibleSpansToVisit:  #If the span does not intersect any of the 3 phase lines, then add it to the list of spans to visit
        if(not CurrentSpan):
            break
        ThreePhaseIntersection=False
        for line in ThreePhaseSpanLines:
            try:
                if(line.intersects(LineString(span.FarStation(CurrentStation).Point, CurrentSpan.FarStation(CurrentStation).Point))):
                    #raise(Exception('Here'))
                    ThreePhaseIntersection=True
            except AttributeError:   #FIXME There is a bug where the current station is not always associated with the current span, Span 65996 for example.
                pass
        if((not ThreePhaseIntersection) and SinglePhaseSpanMakeSureOkToVisit(span, SpansAlreadyVisited, SpansToVisit, CurrentSpan, CurrentStation, CircuitNumber, VisitedThreePhaseTransformerIndicatorList)):
            ConfirmedSpansToVisit.append(span)
    if(ConfirmedSpansToVisit):
        return [ConfirmedSpansToVisit[0]]
    else:
        return []




def CheckWhetherShouldVisitThreePhaseTransformer(station, VisitedPrimaryIndicator, VisitedThreePhaseTransformerIndicatorList):
    if(Assembly.objects.filter(Station=station).filter(CompatibleUnit__TransformerIndicator=True).count()):
        Spans=station.GetNearbySpans()
        ThreePhaseFoundIndicator=False
        for span in Spans:
            if('ABC' in span.GetPhaseCode()):
                ThreePhaseFoundIndicator=True
        if(VisitedPrimaryIndicator and ThreePhaseFoundIndicator):
            return False  #Do not visit a transformer on a 3 phase line if a primary line has already been visited.
        if(not VisitedPrimaryIndicator and ThreePhaseFoundIndicator):
            VisitedThreePhaseTransformerIndicatorList[0] = True  #If this is true, then no primary spans should be visited

    return True
    


def GetStationsNotVisited(SpansToVisit, StationsAlreadyVisited, StationsToVisit, CurrentStation, VisitedPrimaryIndicator, VisitedThreePhaseTransformerIndicatorList):
    #If there is a 3 phase line attached to this station, secondary wire, and a transformer, and 
    #Visited Primary is True, then do not visit this station 
    #Also, if a Primary Transformer Station has been visited, an indicator needs to be checked so that primary line is not visited.

    Stations=[]
    for span in SpansToVisit:
        if(not span.StartStation in StationsAlreadyVisited) and (not span.StartStation in StationsToVisit) and (not span.StartStation == CurrentStation
           and CheckWhetherShouldVisitThreePhaseTransformer(span.StartStation, VisitedPrimaryIndicator, VisitedThreePhaseTransformerIndicatorList)):
            Stations.append(span.StartStation)
        if(not span.EndStation in StationsAlreadyVisited) and (not span.EndStation in StationsToVisit) and (not span.EndStation == CurrentStation):
            Stations.append(span.EndStation)
    return Stations

               

def WalkSinglePhaseLines(meter, VisitedPrimaryIndicatorList):
    """"WalkSinglePhaseLines Returns [meters_connected_by_single_phase_lines, assemblies_connected_by_single_phase_lines]"""
    StationsAlreadyVisited=[]
    SpansAlreadyVisited=[]
    StationsToVisit=[]
    SpansToVisit=[]
    CurrentStation=meter.Station
    CurrentSpan=None
    Assemblies=[]
    #FIXME Seems to be skipping over certain 3 phase pieces, such as around tag# 213067 FIXME
    VisitedThreePhaseTransformerIndicatorList=[False]
    while(True):       
        StationsAlreadyVisited.append(CurrentStation)  #Now visiting the current Station
        SpansToVisit.extend(GetSinglePhaseSpansToVisit(CurrentStation, SpansAlreadyVisited, SpansToVisit, CurrentSpan, meter.CircuitNumber, VisitedThreePhaseTransformerIndicatorList))   #Get all single phase spans (and later backspans) to visit
        StationsToVisit.extend(GetStationsNotVisited(SpansToVisit, StationsAlreadyVisited, StationsToVisit, CurrentStation, 
                                VisitedPrimaryIndicatorList[0], VisitedThreePhaseTransformerIndicatorList))  #Based on those spans being visited, get a list of stations to visit
        Assemblies.extend(list(Assembly.objects.filter(Station=CurrentStation).filter(CircuitNumber=meter.CircuitNumber)))
        for span in SpansToVisit:
            if(not VisitedPrimaryIndicatorList[0] and Assembly.objects.filter(Span=span).filter(CircuitNumber=meter.CircuitNumber).filter(PrimaryIndicator=True)):
                VisitedPrimaryIndicatorList[0]=True     

        if(CurrentSpan):
            Assemblies.extend(list(Assembly.objects.filter(Span=CurrentSpan).filter(CircuitNumber=meter.CircuitNumber)))
            if(not VisitedPrimaryIndicatorList[0] and Assembly.objects.filter(Span=CurrentSpan).filter(CircuitNumber=meter.CircuitNumber).filter(PrimaryIndicator=True)):
                VisitedPrimaryIndicatorList[0]=True
            SpansAlreadyVisited.append(CurrentSpan)
        if(not StationsToVisit):
            break
        if(not SpansToVisit):
            raise(Exception('There are stations left to visit but no spans, this is currently not supported.'))
        CurrentSpan=SpansToVisit.pop()  
        CurrentStation=StationsToVisit.pop()
    Meters=[]
    for assembly in Assemblies:
        if(assembly.CompatibleUnit.MeterIndicator):
            Meters.append(assembly)
    #Text=[]
    #for i in SpansAlreadyVisited:
    #    Text.append(str(i.id))
    #raise(Exception('\n'.join(Text)))
    return Meters, Assemblies




def IsAssemblyTransformerOrSecondaryOffOfThreePhaseTransformer(assembly):
    if(assembly.PrimaryIndicator and not assembly.CompatibleUnit.TransformerIndicator):
       return False
    if(assembly.Span):
        StartStation=assembly.Span.StartStation
    else:
        StartStation=assembly.Station

    StationsToVisit=[StartStation]
    StationsVisited=[]
    SpansVisited=[]
    while(True):
        NearbySpans=StartStation.GetNearbySpans()
        for span in NearbySpans:  #Get a list of all stations connected to the current station using secondary or service
           if(Assembly.objects.filter(Span=span).filter(CompatibleUnit__ConductorIndicator=True).filter(SecondaryIndicator=True).count() or
               Assembly.objects.filter(Span=span).filter(CompatibleUnit__ConductorIndicator=True).filter(ServiceIndicator=True).count()) and (
               not Assembly.objects.filter(Span=span).filter(CompatibleUnit__ConductorIndicator=True).filter(PrimaryIndicator=True).count()):
                if(not span in SpansVisited):
                    SpansVisited.append(span)
                if(not span.FarStation(StartStation) in StationsVisited):
                    StationsToVisit.append(span.FarStation(StartStation))
        #Now check each station to see if it has a primary transformer connected to a 3 phase line
        #If it does, then return True, if not keep checking as long as no primary assemblies are encountered until there are no more stations left to visit
        if(Assembly.objects.filter(Station=StartStation).filter(CompatibleUnit__TransformerIndicator=True)):  #Transformer is the only primary assembly that can return true
           Spans=StartStation.GetNearbySpans()
           ThreePhaseFoundIndicator=False
           for span in Spans:
               if('ABC' in span.GetPhaseCode()):
                   return True
           return ThreePhaseFoundIndicator  #This means we are at a transformer that is not on a 3 phase station, so return false
        if(StationsToVisit):
            StationsVisited.append(StartStation)
            StartStation=StationsToVisit.pop()
        else:
            return False
        
def IsAssemblyAtThreePhaseStationandProtectingASpanNotVisited(assembly, SpansVisited):
    Spans=assembly.Station.GetNearbySpans()
    ThreePhaseFoundIndicator=False
    for span in Spans:
        if('ABC' in span.GetPhaseCode()):
            ThreePhaseFoundIndicator=True
    if(not ThreePhaseFoundIndicator):
        return False
    ProtectingAssemblies=ProtectingAssembly.objects.filter(Assembly=assembly)
    if(not ProtectingAssemblies):
        return False
    ProtectsASpanVisitedIndicator=False
    for protectingAssembly in ProtectingAssemblies:
        if(protectingAssembly.Span in SpansVisited):
            ProtectsASpanVisitedIndicator=True
    return not ProtectsASpanVisitedIndicator  #If any protected spans are in the SpansVisited List, then return False, only care if there are only not SpansVisited being protected


def IsAssemblyOneOfMultipleTransformersAtStationWithMultiplePhaseLines(assembly):
    NumberOfTransformers=Assembly.objects.filter(Station=assembly.Station).filter(CompatibleUnit__TransformerIndicator=True)
    if(NumberOfTransformers < 2):
        return False
    Spans=assembly.Station.GetNearbySpans()
    MultiplePhaseFoundIndicator=False
    PhaseCodeStringList=[]
    for span in Spans:
        PhaseCodeStringList.append(span.GetPhaseCode())
    PhaseCodeString=''.join(PhaseCodeStringList)
    PhasesFound = 0
    if('A' in PhaseCodeString):
        PhasesFound = PhasesFound + 1
    if('B' in PhaseCodeString):
        PhasesFound = PhasesFound + 1
    if('C' in PhaseCodeString):
        PhasesFound = PhasesFound + 1
    if(PhasesFound > 1):
        return True
    return False



def SetSinglePhaseAssemblyPhases(Assemblies, ValidPhaseCodes, StationsUpdated, SpansUpdated, OriginatingMeterDCSINumber, VisitedPrimaryIndicatorList, SpansVisited):
    if(not ValidPhaseCodes):
        return None
    A=ValidPhaseCodes.count('A')
    B=ValidPhaseCodes.count('B')
    C=ValidPhaseCodes.count('C')
    NumberOfAssembliesUpdated=0
    AssembliesUpdatedList=[]

    if(A > B and A > C):
        for assembly in Assemblies:
            if(assembly.CompatibleUnit.MeterIndicator and not assembly.MeterDCSINumber in ['IDLE', '', '0']):  #Meters will be updated from AMR
                continue
            if(assembly.Station and (Assembly.objects.filter(CompatibleUnit__SwitchIndicator=True).filter(Station=assembly.Station).count() > 1)):
                continue
            
            AssemblyPhaseCode=assembly.GetPhaseCode()
            if(AssemblyPhaseCode == 'B' or AssemblyPhaseCode == 'C'):  #Do not change assemblies that have multiple phases
                if(VisitedPrimaryIndicatorList[0] and IsAssemblyTransformerOrSecondaryOffOfThreePhaseTransformer(assembly)):
                    continue
                if(assembly.Station and IsAssemblyAtThreePhaseStationandProtectingASpanNotVisited(assembly, SpansVisited)):
                    continue           
                if(assembly.CompatibleUnit.TransformerIndicator and IsAssemblyOneOfMultipleTransformersAtStationWithMultiplePhaseLines(assembly)):
                    continue
                Log=AMRGISPhaseUpdateLog()
                Log.DateTime=datetime.datetime.now()
                Log.Assembly=assembly
                Log.OriginatingMeterDCSINumber=OriginatingMeterDCSINumber
                Log.PreviousPhaseCode=assembly.GetPhaseCode()
                assembly.PhaseAIndicator=True
                assembly.PhaseBIndicator=False
                assembly.PhaseCIndicator=False
                assembly.save()
                Log.NewPhaseCode=assembly.GetPhaseCode()
                Log.save()
                NumberOfAssembliesUpdated=NumberOfAssembliesUpdated + 1
                AssemblyID=str(assembly.id).ljust(10)
                AssembliesUpdatedList.append(AssemblyID + ' ' +  AssemblyPhaseCode + '-->A')
                if(assembly.Station and not assembly.Station in StationsUpdated):
                    StationsUpdated.append(assembly.Station)
                if(assembly.Span and not assembly.Span in SpansUpdated):
                    SpansUpdated.append(assembly.Span)

    elif(B > A and B > C):
        for assembly in Assemblies:
            if(assembly.CompatibleUnit.MeterIndicator and not assembly.MeterDCSINumber in ['IDLE', '', '0']):  #Meters will be updated from AMR
                continue
            if(assembly.Station and (Assembly.objects.filter(CompatibleUnit__SwitchIndicator=True).filter(Station=assembly.Station).count() > 1)):
                continue
            AssemblyPhaseCode=assembly.GetPhaseCode()
            if(AssemblyPhaseCode == 'A' or AssemblyPhaseCode == 'C'):  #Do not change assemblies that have multiple phases
                if(VisitedPrimaryIndicatorList[0] and IsAssemblyTransformerOrSecondaryOffOfThreePhaseTransformer(assembly)):
                    continue
                if(assembly.Station and IsAssemblyAtThreePhaseStationandProtectingASpanNotVisited(assembly, SpansVisited)):
                    continue           
                if(assembly.CompatibleUnit.TransformerIndicator and IsAssemblyOneOfMultipleTransformersAtStationWithMultiplePhaseLines(assembly)):
                    continue

                Log=AMRGISPhaseUpdateLog()
                Log.DateTime=datetime.datetime.now()
                Log.Assembly=assembly
                Log.OriginatingMeterDCSINumber=OriginatingMeterDCSINumber
                Log.PreviousPhaseCode=assembly.GetPhaseCode()

                assembly.PhaseAIndicator=False
                assembly.PhaseBIndicator=True
                assembly.PhaseCIndicator=False
                assembly.save()
                Log.NewPhaseCode=assembly.GetPhaseCode()
                Log.save()

                NumberOfAssembliesUpdated=NumberOfAssembliesUpdated + 1
                AssemblyID=str(assembly.id).ljust(10)
                AssembliesUpdatedList.append(AssemblyID + ' ' +  AssemblyPhaseCode + '-->B')
                if(assembly.Station and not assembly.Station in StationsUpdated):
                    StationsUpdated.append(assembly.Station)
                if(assembly.Span and not assembly.Span in SpansUpdated):
                    SpansUpdated.append(assembly.Span)
            
    elif(C > A and C > B):
        for assembly in Assemblies:
            if(assembly.CompatibleUnit.MeterIndicator and not assembly.MeterDCSINumber in ['IDLE', '', '0']):  #Meters will be updated from AMR
                continue
            if(assembly.Station and (Assembly.objects.filter(CompatibleUnit__SwitchIndicator=True).filter(Station=assembly.Station).count() > 1)):
                continue
            AssemblyPhaseCode=assembly.GetPhaseCode()
            if(AssemblyPhaseCode == 'A' or AssemblyPhaseCode == 'B'):  #Do not change assemblies that have multiple phases
                if(VisitedPrimaryIndicatorList[0] and IsAssemblyTransformerOrSecondaryOffOfThreePhaseTransformer(assembly)):
                    continue
                if(assembly.Station and IsAssemblyAtThreePhaseStationandProtectingASpanNotVisited(assembly, SpansVisited)):
                    continue           
                if(assembly.CompatibleUnit.TransformerIndicator and IsAssemblyOneOfMultipleTransformersAtStationWithMultiplePhaseLines(assembly)):
                    continue

                Log=AMRGISPhaseUpdateLog()
                Log.DateTime=datetime.datetime.now()
                Log.Assembly=assembly
                Log.OriginatingMeterDCSINumber=OriginatingMeterDCSINumber
                Log.PreviousPhaseCode=assembly.GetPhaseCode()
                assembly.PhaseAIndicator=False
                assembly.PhaseBIndicator=False
                assembly.PhaseCIndicator=True
                assembly.save()
                Log.NewPhaseCode=assembly.GetPhaseCode()
                Log.save()
                NumberOfAssembliesUpdated=NumberOfAssembliesUpdated + 1
                AssemblyID=str(assembly.id).ljust(10)
                AssembliesUpdatedList.append(AssemblyID + ' ' +  AssemblyPhaseCode + '-->C')
                if(assembly.Station and not assembly.Station in StationsUpdated):
                    StationsUpdated.append(assembly.Station)
                if(assembly.Span and not assembly.Span in SpansUpdated):
                    SpansUpdated.append(assembly.Span)
    else:
        return None
    return None




def UpdateSinglePhaseLines(request):
    import django.db
    import decimal
    GenericReportTitle='Update Single Phase Lines'
    GenericMessage='You do not have permission to access this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]


    Meters = Assembly.objects.all().filter(CompatibleUnit__MeterIndicator = True).exclude(MeterDCSINumber__iexact = 'IDLE'\
                      ).exclude(MeterDCSINumber__in=['', 0]).filter(CircuitNumber__gte=0).order_by('CircuitNumber', 'MeterDCSINumber')
    #Meters = Assembly.objects.all().filter(CompatibleUnit__MeterIndicator = True).exclude(MeterDCSINumber__iexact = 'IDLE'\
    #                  ).exclude(MeterDCSINumber__in=['', 0]).filter(MeterDCSINumber__in=[4161905]).filter(CircuitNumber__gte=0).order_by('CircuitNumber', 'MeterDCSINumber')
    SkippedMeters=[] 
    AssembliesVisited=[]
    StationsUpdated=[]
    SpansUpdated=[]
    PreviousCircuitNumber=0
    for meter in Meters:
        if(meter.CircuitNumber > PreviousCircuitNumber):
            PreviousCircuitNumber=meter.CircuitNumber
            for span in SpansUpdated:
                span.RebuildSymbology()
            for station in StationsUpdated:
                station.RebuildSymbology()
            AssembliesVisited=[]
            StationsUpdated=[]
            SpansUpdated=[]
        VisitedPrimaryIndicatorList=[False]
        if(meter in AssembliesVisited):
            continue #Meter was already visited from another meter
        PhaseCode=meter.GetPhaseCode()
        if(len(PhaseCode) != 1):
            continue
        
        MetersOnThisSection, Assemblies = WalkSinglePhaseLines(meter, VisitedPrimaryIndicatorList)
        AssembliesVisited.extend(Assemblies)
        ValidPhaseCodesFound=[]
        MeterDCSINumberList=[]
        for i in MetersOnThisSection:
            if(i.MeterDCSINumber):
                ValidPhaseCodesFound.append(i.GetPhaseCode())
                MeterDCSINumberList.append(i.MeterDCSINumber)
        SpansVisited=[]
        for assembly in Assemblies:
            if(assembly.Span and not assembly.Span in SpansVisited):
                SpansVisited.append(assembly.Span)
        SetSinglePhaseAssemblyPhases(Assemblies, ValidPhaseCodesFound, StationsUpdated, SpansUpdated, meter.MeterDCSINumber, VisitedPrimaryIndicatorList, SpansVisited)  
    for span in SpansUpdated:
        span.RebuildSymbology()
    for station in StationsUpdated:
        station.RebuildSymbology()
    Temp.append('Completed Single Phase Meter Updates.')
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))












#Do not show units if:
#  They are in Remove Status on a Staker Work Order Dated Before 12/01/2011 (excluding stakerworkorders with an EstimateOnlyIndicator=True)
#  They are in Install Status on a Staker Work Order Dated After 11/30/2011
#  They are in Install Status on a Staker Work Order with an EstimateOnlyIndicator=True
#  They are in Install Status on any Staker Work Order that is still in StakerPhase
def GetAssembliesNotIncluded(ConductorsSplitByPhaseList):
    import datetime
    #December01=datetime.datetime(year=2011, month=12, day=01)
    #AssembliesToNotShow=Assembly.objects.all().filter(InstallStatus__Name='Remove').filter(StakerWorkOrder__CreateDate__lte=December01).exclude(StakerWorkOrder__EstimateOnlyIndicator=True) |\
    #               Assembly.objects.filter(InstallStatus__Name='Install').filter(StakerWorkOrder__CreateDate__gte=December01) |\
    #               Assembly.objects.filter(InstallStatus__Name='Install').filter(StakerWorkOrder__EstimateOnlyIndicator=True) |\
    #               Assembly.objects.filter(InstallStatus__Name='Install').filter(StakerWorkOrder__OutToConstructionStartDate__isnull=True)
    AssembliesToNotShow=Assembly.objects.filter(InstallStatus__Name='Install')  #5/2/2012, per SOTT, all Install Assemblies should no longer be shown.
    #Create a dict with # of each of these units so they can just be subtracted out of the totals, no need to a list of every individual unit to be returned.
    AssembliesToNotShowDict={}
    ServicesToNotShowDict={}
    for assembly in AssembliesToNotShow:
        if(assembly.CompatibleUnit.SpanIndicator and not assembly.ServiceIndicator):
            if(assembly.CompatibleUnit.Name in ConductorsSplitByPhaseList):
                Multiplier=len(assembly.GetPhaseCode(True))
            else:
                Multiplier=1
            if assembly.CompatibleUnit.Name in AssembliesToNotShowDict:
                AssembliesToNotShowDict[assembly.CompatibleUnit.Name] = AssembliesToNotShowDict[assembly.CompatibleUnit.Name] + (assembly.Span.Line.length) * Multiplier
            else:
                AssembliesToNotShowDict[assembly.CompatibleUnit.Name] = (assembly.Span.Line.length) * Multiplier
        elif(assembly.CompatibleUnit.SpanIndicator):
            if assembly.CompatibleUnit.Name in ServicesToNotShowDict:
                ServicesToNotShowDict[assembly.CompatibleUnit.Name] = ServicesToNotShowDict[assembly.CompatibleUnit.Name] + 1
            else:
                ServicesToNotShowDict[assembly.CompatibleUnit.Name] = 1
        else:
            if assembly.CompatibleUnit.Name in AssembliesToNotShowDict:
                AssembliesToNotShowDict[assembly.CompatibleUnit.Name] = AssembliesToNotShowDict[assembly.CompatibleUnit.Name] + 1
            else:
                AssembliesToNotShowDict[assembly.CompatibleUnit.Name] = 1

    return AssembliesToNotShowDict, ServicesToNotShowDict





def AssetReport(request):
    import django.db
    GenericReportTitle='COOPGIS Asset Report'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    Temp.append('Test Asset Report')


    ConductorsSplitByPhaseList=['1/0 ACSR', '1/0 ST.15KV', '1/0 ST.25KV', '12 CU', '2/0 ACSR',
                                '2/0 S.WI.AL', '2/3 STRAND', '2 ACSR', '2 ACSR SEC', '2 STR.15KV', '3/0 ACSR', '336.4 ACSR', '350MCM/15KV',
                                '350 MCM/25KV', '350 S.WI.AL', '350 S.WI.AL-SVC', '4/0 ACSR', '4/0 copper single strand', '4/0 COPPER SINGLE STRAND',
                                '4/0 ST.25KV', '477 ACSR', '4 ACSR', '4 ACSR SEC', '4 ACWLD', '4 HARD DRAWN', '4 HD SEC', '500 S.WI.AL',
                                '6 ACWLD', '6 HARD DRAWN', '6 HD SEC', '6 STRAND', '750 MCM', '8 ACWLD', '8 ACWLD SEC', '9 1/2 DCWC']

    AssembliesToNotCountDict, ServicesToNotCountDict=GetAssembliesNotIncluded(ConductorsSplitByPhaseList)
    NameWidth=40
    CountWidth=15
    SubtractWidth=15
    FinalCountWidth=15
    UnitsPrinted=[]
    Temp.append('\nTransformers')
    CompatibleUnits=CompatibleUnit.objects.filter(TransformerIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Count=(Assembly.objects.filter(CompatibleUnit=i).count())
        if(i.Name in AssembliesToNotCountDict.keys()):
            Subtracted=str(AssembliesToNotCountDict[i.Name])
            Count = Count - AssembliesToNotCountDict[i.Name]
        else:
            Subtracted=None
        if(Count > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(Count + int(Subtracted)).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(Count).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(Count).ljust(FinalCountWidth))
            UnitsPrinted.append(i)

    Temp.append('\nReclosers')
    CompatibleUnits=CompatibleUnit.objects.filter(RecloserIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Count=(Assembly.objects.filter(CompatibleUnit=i).count())
        if(i.Name in AssembliesToNotCountDict.keys()):
            Subtracted=str(AssembliesToNotCountDict[i.Name])
            Count = Count - AssembliesToNotCountDict[i.Name]
        else:
            Subtracted=None
        if(Count > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(Count + int(Subtracted)).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(Count).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(Count).ljust(FinalCountWidth))
            UnitsPrinted.append(i)


    Temp.append('\nMeters')
    CompatibleUnits=CompatibleUnit.objects.filter(MeterIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Count=(Assembly.objects.filter(CompatibleUnit=i).count())
        if(i.Name in AssembliesToNotCountDict.keys()):
            Subtracted=str(AssembliesToNotCountDict[i.Name])
            Count = Count - AssembliesToNotCountDict[i.Name]
        else:
            Subtracted=None
        if(Count > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(Count + int(Subtracted)).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(Count).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(Count).ljust(FinalCountWidth))
            UnitsPrinted.append(i)


    Temp.append('\nLights')
    CompatibleUnits=CompatibleUnit.objects.filter(LightIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Count=(Assembly.objects.filter(CompatibleUnit=i).count())
        if(i.Name in AssembliesToNotCountDict.keys()):
            Subtracted=str(AssembliesToNotCountDict[i.Name])
            Count = Count - AssembliesToNotCountDict[i.Name]
        else:
            Subtracted=None
        if(Count > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(Count + int(Subtracted)).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(Count).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(Count).ljust(FinalCountWidth))
            UnitsPrinted.append(i)

    Temp.append('\nPoles')
    CompatibleUnits=CompatibleUnit.objects.filter(PoleIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Count=(Assembly.objects.filter(CompatibleUnit=i).count())
        if(i.Name in AssembliesToNotCountDict.keys()):
            Subtracted=str(AssembliesToNotCountDict[i.Name])
            Count = Count - AssembliesToNotCountDict[i.Name]
        else:
            Subtracted=None
        if(Count > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(Count + int(Subtracted)).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(Count).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(Count).ljust(FinalCountWidth))
            UnitsPrinted.append(i)


    Temp.append('\nServices')
    CompatibleUnits=CompatibleUnit.objects.filter(ConductorIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Count=(Assembly.objects.filter(CompatibleUnit=i).filter(ServiceIndicator=True).count())
        if(i.Name in ServicesToNotCountDict.keys()):
            Subtracted=str(ServicesToNotCountDict[i.Name])
            Count = Count - ServicesToNotCountDict[i.Name]
        else:
            Subtracted=None
        if(Count > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(Count + int(float(Subtracted))).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(Count).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(Count).ljust(FinalCountWidth))
            #UnitsPrinted.append(i)


    Temp.append('\nPrimary Conductors')
    CompatibleUnits=CompatibleUnit.objects.filter(ConductorIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Assemblies=Assembly.objects.filter(CompatibleUnit=i).filter(PrimaryIndicator=True)
        Length = 0
        for assembly in Assemblies:
            if(assembly.CompatibleUnit.Name in ConductorsSplitByPhaseList):
                Multiplier = len(assembly.GetPhaseCode(True))
            else:
                Multiplier = 1
            Length = Length + (Multiplier * assembly.Span.Line.length)

        if(i.Name in AssembliesToNotCountDict.keys()):
            Subtracted=str(int(AssembliesToNotCountDict[i.Name]))
            Length = int(Length) - int(AssembliesToNotCountDict[i.Name])
        else:
            Subtracted=None
        if(Length > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(int(float(Length)) + int(float(Subtracted))).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(int(float(Length))).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(int(float(Length))).ljust(FinalCountWidth))
            UnitsPrinted.append(i)


    Temp.append('\nSecondary Conductors')
    CompatibleUnits=CompatibleUnit.objects.filter(ConductorIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Assemblies=Assembly.objects.filter(CompatibleUnit=i).filter(SecondaryIndicator=True)
        Length = 0
        for assembly in Assemblies:
            if(assembly.CompatibleUnit.Name in ConductorsSplitByPhaseList):
                Multiplier = len(assembly.GetPhaseCode(True))
            else:
                Multiplier = 1
            Length = Length + (Multiplier * assembly.Span.Line.length)

        if(i.Name in AssembliesToNotCountDict.keys()):
            Subtracted=str(int(AssembliesToNotCountDict[i.Name]))
            Length = int(Length) - int(AssembliesToNotCountDict[i.Name])
        else:
            Subtracted=None
        if(Length > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(int(float(Length)) + int(float(Subtracted))).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(int(float(Length))).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(int(float(Length))).ljust(FinalCountWidth))
            UnitsPrinted.append(i)




    Temp.append('\nOther Station Compatible Units')
    CompatibleUnits=CompatibleUnit.objects.all().filter(StationIndicator=True).order_by('Name')
    for i in CompatibleUnits:
        if(i in UnitsPrinted):
            continue
        Count=(Assembly.objects.filter(CompatibleUnit=i).count())
        if(i.Name in AssembliesToNotCountDict.keys()):
            Subtracted=str(AssembliesToNotCountDict[i.Name])
            Count = Count - AssembliesToNotCountDict[i.Name]
        else:
            Subtracted=None
        if(Count > 0):
            if(Subtracted):
                Temp.append(i.Name.ljust(NameWidth) + str(Count + int(Subtracted)).ljust(CountWidth) + str('-' + Subtracted).ljust(SubtractWidth) + str(Count).ljust(FinalCountWidth))
            else:
                Temp.append(i.Name.ljust(NameWidth) + ''.ljust(CountWidth)                           + ''.ljust(SubtractWidth)                    + str(Count).ljust(FinalCountWidth))
            UnitsPrinted.append(i)
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))



@transaction.commit_on_success
def AMRGISPhaseUpdateLogView(request):
    import django.db
    GenericReportTitle='COOPGIS AMR GIS Phase Update Log View'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    import datetime
    StartDateTime=datetime.datetime.now() - datetime.timedelta(days=50)
    Logs=AMRGISPhaseUpdateLog.objects.filter(DateTime__gte=StartDateTime).order_by('DateTime') 
    Temp.append('Log Count Length:  ' + str(len(Logs)))
    Temp.append('Originating DCSI Number'.ljust(20) + 'Station'.ljust(10) + 'Span'.ljust(10) + 'Assemblyid'.ljust(12) + 
                'Previous'.ljust(10) + 'New'.ljust(10) + 'Assembly Name')
    for log in Logs:
        if(log.Assembly.Station):
            Stationid=log.Assembly.Station.id
        else:
            Stationid = ''
        if(log.Assembly.Span):
            Spanid=log.Assembly.Span.id
        else:
            Spanid = ''
        Temp.append(str(log.OriginatingMeterDCSINumber).ljust(20) + str(Stationid).ljust(10) + str(Spanid).ljust(10) + str(log.Assembly.id).ljust(12) + 
                    str(log.PreviousPhaseCode).ljust(10) + str(log.NewPhaseCode).ljust(10) + str(log.Assembly.CompatibleUnit.Name))
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))














@transaction.commit_on_success
def UnprotectedAssemblySpans(request):
    import django.db
    GenericReportTitle='COOPGIS Assemblies That Lack Protected Spans'
    GenericMessage='You do not have permission to use this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    RecloserAssemblies=Assembly.objects.filter(CompatibleUnit__RecloserIndicator=True)
    CutOutAssemblies=Assembly.objects.filter(CompatibleUnit__CutOutIndicator=True)
    SwitchAssemblies=Assembly.objects.filter(CompatibleUnit__SwitchIndicator=True)
    Temp.append('RECLOSER ASSEMBLIES')
    Temp.append('Assembly ID'.ljust(15) + 'Station ID'.ljust(15) + 'Staker Work Order Status')
    for assembly in RecloserAssemblies.order_by('Station__id'):
        ProtectingAssemblies=ProtectingAssembly.objects.filter(Assembly=assembly)
        if ProtectingAssemblies.count():
            continue
        Row=str(assembly.id).ljust(15) + str(assembly.Station.id).ljust(15)
        SymbologyWorkOrders=SymbologyStakerWorkOrderStation.objects.filter(Station=assembly.Station)
        WorkOrdersWithPhase=[]
        for i in SymbologyWorkOrders:
            WorkOrderInfo=i.StakerWorkOrder.GetIDPhaseString()
            if WorkOrderInfo in WorkOrdersWithPhase:
                continue
            WorkOrdersWithPhase.append(WorkOrderInfo)
        Row+=str(WorkOrdersWithPhase)
        Temp.append(Row)
    Temp.append('\n\nCUTOUT ASSEMBLIES')
    Temp.append('Assembly ID'.ljust(15) + 'Station ID'.ljust(15) + 'Staker Work Order Status')
    for assembly in CutOutAssemblies.order_by('Station__id'):
        ProtectingAssemblies=ProtectingAssembly.objects.filter(Assembly=assembly)
        if ProtectingAssemblies.count():
            continue
        Row=str(assembly.id).ljust(15) + str(assembly.Station.id).ljust(15)
        SymbologyWorkOrders=SymbologyStakerWorkOrderStation.objects.filter(Station=assembly.Station)
        WorkOrdersWithPhase=[]
        for i in SymbologyWorkOrders:
            WorkOrderInfo=i.StakerWorkOrder.GetIDPhaseString()
            if WorkOrderInfo in WorkOrdersWithPhase:
                continue
            WorkOrdersWithPhase.append(WorkOrderInfo)
        Row+=str(WorkOrdersWithPhase)
        Temp.append(Row)
    Temp.append('\n\nSWITCH ASSEMBLIES')
    Temp.append('Assembly ID'.ljust(15) + 'Station ID'.ljust(15) + 'Staker Work Order Status')
    for assembly in SwitchAssemblies.order_by('Station__id'):
        Row=str(assembly.id).ljust(15) + str(assembly.Station.id).ljust(15)
        SymbologyWorkOrders=SymbologyStakerWorkOrderStation.objects.filter(Station=assembly.Station)
        WorkOrdersWithPhase=[]
        for i in SymbologyWorkOrders:
            WorkOrderInfo=i.StakerWorkOrder.GetIDPhaseString()
            if WorkOrderInfo in WorkOrdersWithPhase:
                continue
            WorkOrdersWithPhase.append(WorkOrderInfo)
        Row+=str(WorkOrdersWithPhase)
        Temp.append(Row)
    Preformatted='\n'.join(Temp)
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))



@transaction.commit_on_success
def OldTransformers(request):
    import django.db
    GenericReportTitle='COOPGIS Assemblies Named \"Transformer\"'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    Temp.append('Circuit Number'.ljust(20) + 'Station ID'.ljust(20) + 'CompatibleUnit Name'.ljust(20))    
    Assemblies = Assembly.objects.all().filter(CompatibleUnit__Name__iexact = 'transformer').order_by('CircuitNumber', 'Station__id')
    for assembly in Assemblies:
        Temp.append(str(assembly.CircuitNumber).ljust(20) + str(assembly.Station.id).ljust(20) + str(assembly.CompatibleUnit.Name).ljust(20))
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))


@transaction.commit_on_success
def ShowDuplicateGISMeterNumbers(request):
    """This report shows a list of duplicated meters in the GIS that match CIS meter numbers"""
    import django.db
    GenericReportTitle='COOPGIS Show Duplicate GIS Meter Numbers'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISCISApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    #Perform Data Gathering Tasks
    #Also get a list of GIS locations for which more then 1 have the same map number
    Meters=list(Assembly.objects.filter(CompatibleUnit__MeterIndicator=True).order_by('id'))
    MeterNumbersAlreadyProcessed=[]
 
   #Now Show the Duplicated Meter Numbers in the GIS
    Temp.append('Duplicated GIS Meters')
    Temp.append('Station'.ljust(20) +  'Installstatus'.ljust(20) + 'MeterDCSINumber'.ljust(20))
    for i in Meters:
        if(i.MeterDCSINumber in MeterNumbersAlreadyProcessed) or (len(i.MeterDCSINumber) < 5):
            continue
        else:
            MeterNumbersAlreadyProcessed.append(i.MeterDCSINumber)
        MatchesFound = 0
        Results=[]
        for meter in Meters:
            if(meter.MeterDCSINumber == i.MeterDCSINumber):
                MatchesFound = MatchesFound + 1
                Results.append(meter)
        if(MatchesFound > 1):
            for j in Results:
                Temp.append(str(j.Station.id).ljust(20) +  j.InstallStatus.Name.ljust(20) + j.MeterDCSINumber.ljust(20))
                
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))




@transaction.commit_on_success
def ImproperlyArchivedAssemblies(request):
    """This report shows a list of assemblies with archived stakerworkorders whose own install status is set to Remove
     These should have been taken care of during the normal stakerworkorder archiving process;
     This issue will be addressed in StakerWorkOrder v2"""
    import django.db
    GenericReportTitle='COOPGIS Assemblies Marked Remove That Exist After Archiving'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    Assemblies=Assembly.objects.filter(StakerWorkOrder__ArchivedIndicator=True).filter(InstallStatus__Name='Remove').order_by('id')
    Temp.append('# of Undeleted Archived Assemblies: ' + str(Assemblies.count()))
    Temp.append('')
    Temp.append('Station/Span'.ljust(15) + 'CompatibleUnit'.ljust(25) + 'WorkOrderid'.ljust(15) + 'StakerWorkOrderName')
    for a in Assemblies:
        if a.CompatibleUnit.StationIndicator:
            StationSpanid=str(a.Station.id)
        elif a.CompatibleUnit.SpanIndicator:
            StationSpanid=str(a.Span.id)
        Temp.append(StationSpanid.ljust(15) + a.CompatibleUnit.Name.ljust(25) + str(a.StakerWorkOrder.id).ljust(15) + a.StakerWorkOrder.Name)

    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))

@transaction.commit_on_success
def DuplicatePoles(request):
    """This report shows a list of Stations that have more an archived stakerworkorder and more than one pole"""
    import django.db
    GenericReportTitle='COOPGIS Report Duplicate Pole Stations (Archived Work Orders Only)'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    Temp.append('Stationid'.ljust(15) + 'Pole List')
    for station in Station.objects.all().order_by('id'):
        StationWorkOrder=Assembly.objects.filter(StakerWorkOrder__ArchivedIndicator=True).filter(Station=station)
        if not StationWorkOrder.count():
            continue
        Poles=Assembly.objects.filter(Station=station).filter(CompatibleUnit__PoleIndicator=True)
        if Poles.count() > 1:
            PoleList=[]
            for p in Poles:
                PoleList.append(p.id)
            Temp.append(str(station.id).ljust(15) + str(PoleList))
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))

def GetPolesWithoutCopperAtStation():
    Results=[]
    ExemptPoles=['P0-0', 'P1', 'P16-5','P2','P20BSB','P3','P30-BSB','P30-PKW'] #do not require copper
    Poles=Assembly.objects.filter(CompatibleUnit__PoleIndicator=True).exclude(CompatibleUnit__Name__in=ExemptPoles).order_by('CircuitNumber')
    for pole in Poles:
        station=pole.Station
        Copper=Assembly.objects.filter(Station=station).filter(CompatibleUnit__Name__icontains='cw')|Assembly.objects.filter(
               Station=station).filter(CompatibleUnit__Name__icontains='sd')
        if Copper.exists():
            continue
        Results.append(pole)
    return Results

@transaction.commit_on_success
def NoCopperPoles(request):
    """This report shows a list of Poles/Stations that lack copper (CompatibleUnit containing copper wire or soft draw) and 
       their associated work orders"""
    import django.db
    GenericReportTitle='COOPGIS Report Poles Without Copper'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    PolesWithoutCopper=GetPolesWithoutCopperAtStation()
    Temp.append('Circuit#'.ljust(15) + 'Pole Tag#'.ljust(15) + 'CompatibleUnit'.ljust(25) + 'Station ID'.ljust(15) + 'Station WorkOrders')
    for pole in PolesWithoutCopper:
        SymbologyWorkOrders=SymbologyStakerWorkOrderStation.objects.filter(Station=pole.Station)
        Row=str(pole.CircuitNumber).ljust(15) + pole.TagNumber.ljust(15) + pole.CompatibleUnit.Name.ljust(25) + str(pole.Station.id).ljust(15)
        if SymbologyWorkOrders.count():
            WorkOrdersWithPhase=[]
            for i in SymbologyWorkOrders:
                WorkOrdersWithPhase.append(i.StakerWorkOrder.GetIDPhaseString())
            Row+=str(WorkOrdersWithPhase)
        Temp.append(Row)
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))

@transaction.commit_on_success
def DuplicateOldMapNumbers(request):
    """This report shows a list of Assemblies that have duplicate old map numbers, along with station and stakerworkorder information"""
    import django.db
    GenericReportTitle='COOPGIS Report Duplicate Old MapNumbers'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    Temp.append('Station ID'.ljust(15) + 'Assembly ID'.ljust(15) + 'Name'.ljust(25) + 'OldMapNumber'.ljust(25) + 'StakerWorkOrders')
    OldMapNumbers=[]
    DuplicateAssemblies=[]
    Assemblies=Assembly.objects.exclude(OldMapNumber='').order_by('Station__id', 'id')
    for assembly in Assemblies:
        number=assembly.OldMapNumber
        if not number in OldMapNumbers:
            OldMapNumbers.append(number)
    for number in OldMapNumbers:
        MatchingAssemblies=Assembly.objects.filter(OldMapNumber=number)
        if MatchingAssemblies.count() <= 1:
            continue
        for assembly in MatchingAssemblies:
            DuplicateAssemblies.append(assembly)
    for i in DuplicateAssemblies:
        WorkOrderSymbology=SymbologyStakerWorkOrderStation.objects.filter(Station=i.Station)
        RowString=str(i.Station.id).ljust(15) + str(i.id).ljust(15) + i.CompatibleUnit.Name.ljust(25) + i.OldMapNumber.ljust(25)
        if not WorkOrderSymbology.count():
            continue
        WorkOrdersWithPhase=[]
        for i in WorkOrderSymbology:
            WorkOrderInfo=i.StakerWorkOrder.GetIDPhaseString()
            if WorkOrderInfo in WorkOrdersWithPhase:
                continue
            WorkOrdersWithPhase.append(WorkOrderInfo)
        RowString+=str(WorkOrdersWithPhase)
        Temp.append(RowString)
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))

@transaction.commit_on_success
def MapNumberErrors(request):
    """This report shows a list of Assemblies that should not have mapnumbers but do; also, lights/meters that lack a new map number"""
    import django.db
    GenericReportTitle='COOPGIS Report Assemblies With Unassigned/Misassigned MapNumbers'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISStakerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Temp=[]
    Temp.append('Non-Meter Assemblies That Have OldMapNumbers')
    Temp.append('Station ID'.ljust(15) + 'Assembly ID'.ljust(15) + 'Name'.ljust(25) + 'OldMapNumber')
    Assemblies=Assembly.objects.exclude(CompatibleUnit__MeterIndicator=True).exclude(OldMapNumber='')
    for assembly in Assemblies.order_by('Station__id','id'):
        Temp.append(str(assembly.Station.id).ljust(15) + str(assembly.id).ljust(15) + assembly.CompatibleUnit.Name.ljust(25) + assembly.OldMapNumber)

    Temp.append('\n\nMeters Missing OldMapNumbers or MapNumbers')
    Temp.append('Station ID'.ljust(15) + 'AssemblyID'.ljust(15) + 'Name'.ljust(25) + 'OldMapNumber'.ljust(20) + 'MapNumber')
    Assemblies=Assembly.objects.filter(CompatibleUnit__MeterIndicator=True).filter(OldMapNumber='')
    for i in Assemblies.order_by('Station__id'):
        Row=str(i.Station.id).ljust(15) + str(i.id).ljust(15) + i.CompatibleUnit.Name.ljust(25)
        if i.OldMapNumber:
            Row+=i.OldMapNumber.ljust(20)
        else:
            Row+=''.ljust(20)
        if i.MapNumber:
            Row+=str(i.MapNumber)
        else:
            pass
        Temp.append(Row)

    Temp.append('\n\nLights Missing MapNumbers')
    Temp.append('Station ID'.ljust(15)  + 'Assembly ID'.ljust(15) + 'Name'.ljust(25))
    Assemblies=Assembly.objects.filter(CompatibleUnit__LightIndicator=True).filter(MapNumber__isnull=True)
    for i in Assemblies:
        Temp.append(str(i.Station.id).ljust(15) + str(i.id).ljust(15) + i.CompatibleUnit.Name.ljust(25))
    
    Preformatted='\n'.join(Temp)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))

@transaction.commit_on_success
def OutdoorLightingConditionsByCircuitNumber(request):
    """This report shows all CircuitNumbers with the most recent Condition and that Condition's username, createdatetime, etc"""
    import django.db
    GenericReportTitle='COOPGIS Report Condition Information by Circuit Number'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISInventoryCollectionApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    #Start Data Gathering Tasks
    Report=[]
    CircuitNumbers=list(Assembly.objects.values_list('CircuitNumber', flat=True).distinct())
    CircuitNumbers.sort()
    ActiveConditions=Condition.objects.filter(PriorityOutdoorLightingConversionIndicator=True).exclude(ArchivedIndicator=True).exclude(DeletedIndicator=True)
    Report.append('Circuit'.ljust(10) + 'Most Recently Created Condition'.ljust(35) + 'Most Recently Modified Condition'.ljust(35))
    Report.append(''.ljust(10) + 'ID'.ljust(5) + 'User'.ljust(10) + 'DateTime'.ljust(20) + 'ID'.ljust(5) + 'User'.ljust(10) + 'DateTime'.ljust(20))

    for i in CircuitNumbers:
        Row=''
        Row+=str(i).ljust(10)
        for condition in ActiveConditions.order_by('-CreateDateTime'):
            ConditionCircuitNumbers=list(condition.CircuitNumbers.split(','))
            if str(i) in ConditionCircuitNumbers:
                RecentlyCreatedCondition=condition
                break
        else:
            RecentlyCreatedCondition=None
        for condition in ActiveConditions.order_by('-LastModifyDateTime'):
            ConditionCircuitNumbers=list(condition.CircuitNumbers.split(','))
            if str(i) in ConditionCircuitNumbers:
                RecentlyModifiedCondition=condition
                break
        else:
            RecentlyModifiedCondition=None
        if RecentlyCreatedCondition:
            Row+=(str(RecentlyCreatedCondition.id).ljust(5) + RecentlyCreatedCondition.CreateUserName.ljust(10) +
                           str(RecentlyModifiedCondition.CreateDateTime)[:19].ljust(20))
        else:
            Row+=''.ljust(35)
        if RecentlyModifiedCondition and not RecentlyModifiedCondition == RecentlyCreatedCondition:
            Row+=(str(RecentlyModifiedCondition.id).ljust(5) + RecentlyModifiedCondition.CreateUserName.ljust(10) +
                           RecentlyModifiedCondition.LastModifyUserName.ljust(10) + str(RecentlyModifiedCondition.LastModifyDateTime)[:19].ljust(20))
        Report.append(Row)
    Preformatted='\n'.join(Report)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))


@transaction.commit_on_success
def OutdoorLightingUniqueLightMapNumber(request):
    """Checks for unique mapnumbers for all Assembly Lights"""
    import django.db
    GenericReportTitle='COOPGIS Report Unique Light Map Numbers'
    GenericMessage='You do not have permission to use this application.'
    ApplicationName=djangoproject.settings.COOPGISInventoryCollectionApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle, 'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    #Start Data Gathering Tasks
    Report=[]
    AssemblyLights=Assembly.objects.filter(CompatibleUnit__LightIndicator=True)
    LightMapNumbers=AssemblyLights.values_list('MapNumber', flat=True)
    Existing=[]
    Duplicates=[]
    for i in LightMapNumbers:
        if i in Existing and not i in Duplicates:
            Duplicates.append(i)
            continue
        Existing.append(i)
    Report.append('MapNumber'.ljust(15) + 'Count'.ljust(10) + 'Assembly/Stations')
    for mapnumber in Duplicates:
        DuplicateLights = AssemblyLights.filter(MapNumber=mapnumber)
        DuplicateLightCount = str(DuplicateLights.count())
        SummaryString = ''
        for i in DuplicateLights:
            SummaryString += ('ID: ' + str(i.id) + '; Station: ' + str(i.Station.id) + ''.ljust(5))
        Stations = AssemblyLights.values_list('Station', flat=True)
        Report.append(str(mapnumber).ljust(15) + DuplicateLightCount.ljust(10) + SummaryString)
    Report.append('')
    Report.append('Lights with Non-Integer MapNumbers:')
    Report.append('Assembly ID')
    for i in list(AssemblyLights):
        try:
            Temp=int(i.MapNumber)
        except:
            Report.append(str(i.id))
    Preformatted='\n'.join(Report)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle, 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))

@transaction.commit_on_success
def OutdoorLightingIdle(request):
    """Shows conditions with idle status"""
    import django.db
    GenericReportTitle='COOPGIS Report Idle Conditions'
    GenericMessage='You do not have permission to use this application.'
    ApplicationName=djangoproject.settings.COOPGISInventoryCollectionApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle, 'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    #Start Data Gathering Tasks
    Report=[]
    IdleConditions=Condition.objects.filter(OutdoorLightIdleIndicator=True)
    Report.append('ID'.ljust(5) + 'OL'.ljust(7) + 'Created By'.ljust(30) + 'Modified'.ljust(30) +
                  'Map #'.ljust(15) + 'Meter #'.ljust(15) + 'MeterMap #'.ljust(15) + 'Tag #'.ljust(15) + 'Station id')
    for i in IdleConditions:
        ID=str(i.id)
        OL=str(i.PriorityOutdoorLightingConversionIndicator)
        Created=i.CreateUserName + ' ' + i.CreateDateTime.strftime('%Y-%m-%d %H:%M')
        if i.LastModifyDateTime:
            ModifiedDateString = i.LastModifyDateTime.strftime('%Y-%m-%d %H:%M')
        else:
            ModifiedDateString = ''
        Modified=i.LastModifyUserName + ' ' + ModifiedDateString
        Map=str(i.OutdoorLightMapNumber)
        Meter=str(i.OutdoorLightMeterNumber)
        MeterMap=str(i.OutdoorLightMeterMapNumber)
        Tag=str(i.TagNumber)
        Station=str(i.StationIdentifier)
        Report.append(ID.ljust(5) + OL.ljust(7) + Created.ljust(30) + Modified.ljust(30) + Map.ljust(15) + 
                      Meter.ljust(15) + MeterMap.ljust(15) + Tag.ljust(15) + Station)
    Preformatted='\n'.join(Report)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 
                 'GenericReportTitle': GenericReportTitle, 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))

@transaction.commit_on_success
def OutdoorLightingSendToBilling(request):
    """Allows users to edit selected fields of non-archived Conditions (most likely those from OutdoorLighting) and send them to COOPIP"""
    import django.db
    ApplicationName=djangoproject.settings.COOPGISInventoryCollectionApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    GenericReportTitle = 'OutdoorLighting Send to Billing Phase'
    GenericMessage = ''
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle, 'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Conditions = Condition.objects.filter(OutdoorLightGISPhaseIndicator=True).filter(OutdoorLightBillingWorkStartedIndicator=True).exclude(
                                  ArchivedIndicator=True).exclude(DeletedIndicator=True).order_by('id')
    NumberOfConditionsListedOnForm=Conditions.count()
    SpecialBuildFormInfo={}
    SpecialBuildFormInfo['NumberOfConditionsListedOnForm'] = NumberOfConditionsListedOnForm
    form=COOPGIS_FormMisc.BuildForm(request, 'OutdoorLightingSendToBilling', SpecialBuildFormInfo=SpecialBuildFormInfo)
    for conditionFormNumber in range(0, NumberOfConditionsListedOnForm):
        COOPGIS_FormMaintenance.ProcessOutdoorLightingSendToBillingFormEntry(form, conditionFormNumber, UserNameOrIPAddress)
    form=COOPGIS_FormMaintenance.PopulateOutdoorLightingSendToBillingForm(form, list(Conditions))
    NumberOfConditionsListedOnForm=Conditions.count()
    SpecialBuildFormInfo['NumberOfConditionsListedOnForm'] = NumberOfConditionsListedOnForm
    form=COOPGIS_FormMisc.BuildForm(request, 'OutdoorLightingSendToBilling', SpecialBuildFormInfo=SpecialBuildFormInfo)
    form=COOPGIS_FormMaintenance.PopulateOutdoorLightingSendToBillingForm(form, list(Conditions))
    COOPGIS_DynamicTemplate.UpdateOutdoorLightingSendToBillingTemplate(list(Conditions), UserNameOrIPAddress)

    t = loader.get_template('/opt/coopgis/djangoproject/templates/outdoorlightingsendtobilling_' + UserNameOrIPAddress + '.html')
    c = Context({'LoginStatus' : LoginStatus, 'form':form, 'GenericReportTitle': GenericReportTitle})
    return HttpResponse(t.render(c))



@transaction.commit_on_success
def VegetationManagerJobSpanLength(request):
    """Length of VegetationManager JobSpans within each VegetationManagerJob"""
    import django.db
    GenericReportTitle='COOPGIS Report VegetationManagerJobSpan Length'
    GenericMessage='You do not have permission to use this application.'
    ApplicationName=djangoproject.settings.COOPGISVegetationManagerApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle, 'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Report=[]
    Report.append('Job ID'.ljust(10) + 'Description'.ljust(45) + 'Span Count'.ljust(15) +
                  'Primary Overhead'.ljust(25) + 'Secondary Overhead'.ljust(25))
    Jobs=VegetationManagerJob.objects.all()
    for job in Jobs:
        PrimaryLength=0.0
        SecondaryLength=0.0
        JobSpans = VegetationManagerJobSpan.objects.filter(VegetationManagerJob = job)
        for jobspan in JobSpans:
            PrimaryLine = SymbologyPrimaryLine.objects.filter(Span__id=jobspan.Spanid)
            if PrimaryLine.exists():                
                PrimaryLength += jobspan.Line.length
                continue                
            SecondaryLine = SymbologySecondaryLine.objects.filter(Span__id=jobspan.Spanid)
            if SecondaryLine.exists():
                SecondaryLength += jobspan.Line.length
        ID = str(job.id)
        Description = job.Description[:40].replace('\r', '').replace('\n', '')
        SpanCount = str(JobSpans.count())
        Primary = str(PrimaryLength / 5280.0) + ' mi'
        Secondary = str(SecondaryLength / 5280.0) + ' mi'
        Report.append(ID.ljust(10) + Description.ljust(45) + SpanCount.ljust(15) + Primary.ljust(25) + Secondary.ljust(25))
    Preformatted='\n'.join(Report)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 
                 'GenericReportTitle': GenericReportTitle, 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))


@transaction.commit_on_success
def StationsWithoutAssemblies(request):
    import django.db
    GenericReportTitle='COOPGIS Stations Without Assemblies'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISInventoryCollectionApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Report=[]
    #stations with no assemblies
    EmptyStations = []
    #circuitnumber, then station pairs of stations lacking poles and underground/service assemblies
    CircuitStationPairs = []
    for i in Station.objects.values_list('id', flat=True):
        StationAssemblies = Assembly.objects.filter(Station__id=i)
        if not StationAssemblies.count():
            EmptyStations.append(str(i))
            continue
        Pole = StationAssemblies.filter(CompatibleUnit__PoleIndicator=True)
        if Pole.count():
            continue
        Services = StationAssemblies.filter(ServiceIndicator=True)
        if Services.count():
            continue
        #UG: underground assembly; UK-6: vault; UM and VUM per RWise
        Underground = StationAssemblies.filter(CompatibleUnit__Name__contains='UG') | StationAssemblies.filter(CompatibleUnit__Name='UK-6') | StationAssemblies.filter(CompatibleUnit__URDMarkerIndicator=True) | StationAssemblies.filter(CompatibleUnit__Name__startswith='UM') | StationAssemblies.filter(CompatibleUnit__Name__startswith='VUM')
        if Underground.count():
            continue
        Circuits = StationAssemblies.values_list('CircuitNumber', flat=True).distinct()
        CircuitStationPairs.append((Circuits[0], str(i)))
    Report.append('Empty Stations (No Assemblies)')
    EmptyStations.sort()
    for i in EmptyStations:
        Report.append(i)
    Report.append('')
    Report.append('')
    Report.append('')
    Report.append('Stations Without Poles or Service Assemblies')
    Report.append('Circuit'.ljust(15) + 'Station'.ljust(15))
    CircuitStationPairs.sort()
    for i in CircuitStationPairs:
        circuit, station = i
        Report.append(str(circuit).ljust(15) + station.ljust(15))
    Preformatted='\n'.join(Report)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))


@transaction.commit_on_success
def LengthOfEachCircuitReport(request):
    import django.db
    GenericReportTitle='COOPGIS Length of Each Circuit Report'
    GenericMessage='You do not have permission to this application.'
    ApplicationName=djangoproject.settings.COOPGISInventoryCollectionApplicationName
    UserNameOrIPAddress=COOPGIS_Misc.GetUserNameOrIPAddress(request, GetDefaultMap=False, ApplicationName=ApplicationName)
    LoginStatus, applicationPermission=COOPGIS_Misc.CheckLoginPermissions(request, ApplicationName)
    if(not applicationPermission):
        t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
        c = Context({'LoginStatus' : LoginStatus, 'GenericReportTitle': GenericReportTitle,
                     'GenericMessage': GenericMessage})
        return HttpResponse(t.render(c))
    Report=[]
    #stations with no assemblies
    Spans = Span.objects.all()
    Report.append('Circuit Number'.ljust(35) + 'Circuit Name(s)'.ljust(90) + 'Phases'.ljust(15) +  'Length (ft)')

    CircuitDictionary = {}  #Circuit Numbers + PhaseCodes=['[Circuit Numbers]', '[Circuit Names]', 'PhaseCode', Length]
    for i in Spans:
        WiresCount=Assembly.objects.filter(Span=i).filter(CompatibleUnit__ConductorIndicator=True).filter(PrimaryIndicator=True).exclude(CompatibleUnit__NormallyUndergroundIndicator=True).count()
        if(WiresCount):
            PrimaryString='Primary'
        else:
            WiresCount=Assembly.objects.filter(Span=i).filter(CompatibleUnit__ConductorIndicator=True).exclude(CompatibleUnit__NormallyUndergroundIndicator=True).count()
            if(WiresCount):
                PrimaryString='Secondary/Service'
            else:
                continue  #Do not count any spans with no wires
        

        Length = i.Line.length
        PhaseCodes = str(len(i.GetPhaseCode(IncludeNeutral = False)))
        Circuits = i.GetCircuitNumbers()
        

        if(not CircuitDictionary.has_key(str(Circuits) + PhaseCodes + PrimaryString)):
            CircuitDictionary[str(Circuits)+PhaseCodes + PrimaryString] = [Circuits, 'No Names Yet', str(PhaseCodes), Length, PrimaryString]
        else:
            CircuitDictionary[str(Circuits)+PhaseCodes + PrimaryString][3] = CircuitDictionary[str(Circuits)+PhaseCodes + PrimaryString][3] + Length
    Keys = CircuitDictionary.keys()
    Keys.sort()
    for key in Keys:
        CircuitNumbers = CircuitDictionary[key][0]
        CircuitNames = []
        CircuitNumbersString = ''
        for i in CircuitNumbers:
            try:
                CircuitNames.append(SubstationCircuit.objects.filter(CircuitNumber=i)[0].Name)
            except:
                CircuitNames.append('Unknown')
            if(CircuitNumbersString):
                CircuitNumbersString = CircuitNumbersString + ', '
            CircuitNumbersString = CircuitNumbersString + str(i)

        CircuitNames = ', '.join(CircuitNames)
        Length = int(CircuitDictionary[key][3])
        Report.append(CircuitNumbersString.ljust(35) + CircuitNames.ljust(90) + str(CircuitDictionary[key][2]).ljust(15) + str(Length).ljust(15) + str(CircuitDictionary[key][4]).ljust(15))
    Preformatted='\n'.join(Report)
    #End Data Gathering Tasks
    GenericMessage=''
    t = loader.get_template('/opt/coopgis/djangoproject/templates/genericreporttemplate.html')
    c = Context({'LoginStatus' : LoginStatus, 'Preformatted': Preformatted, 'GenericReportTitle': GenericReportTitle,
                 'GenericMessage': GenericMessage})
    return HttpResponse(t.render(c))
